package main

import "syscall"

// epoll events
// syscall.EPOLLIN
// syscall.EPOLLOUT

type Epoll struct {
	fd int
}

func CreateEpoll() *Epoll {
	p := &Epoll{}
	fd, err := syscall.EpollCreate1(0)
	if err != nil {
		return nil
	}
	p.fd = fd
	return p
}

func (p *Epoll) Close() error {
	return syscall.Close(p.fd)
}

func (p *Epoll) Wait(n int) ([]syscall.EpollEvent, error) {
	events := make([]syscall.EpollEvent, n)
	for {
		num, err := syscall.EpollWait(p.fd, events, -1)
		switch err {
		case nil:
			return events[:num], nil
		case syscall.EINTR, syscall.EAGAIN:
			// retry
		default:
			return nil, err
		}
	}
	return nil, nil
}

func (p *Epoll) Add(fd int, events uint32) error {
	return syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_ADD, fd,
		&syscall.EpollEvent{
			Fd:     int32(fd),
			Events: events,
		})
}

func (p *Epoll) Mod(fd int, events uint32) error {
	return syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_MOD, fd,
		&syscall.EpollEvent{
			Fd:     int32(fd),
			Events: events,
		})
}

func (p *Epoll) Del(fd int) error {
	return syscall.EpollCtl(p.fd, syscall.EPOLL_CTL_DEL, fd,
		&syscall.EpollEvent{})
}
